package cn.b.sky.mes.pp.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import cn.b.sky.mes.pp.service.OperationConfirmService;
import cn.b.sky.mes.pp.utils.NumberUtils;
import cn.b.sky.shop.activiti.service.impl.EvunProcessEngine;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import cn.b.sky.mes.cm.model.ProcessComponent;
import cn.b.sky.mes.cm.model.ProcessOperation;
import cn.b.sky.mes.cm.service.ProcessService;
import cn.b.sky.mes.cm.service.WorkUnitService;
import cn.b.sky.mes.mm.constants.MmConstant;
import cn.b.sky.mes.mm.model.MoveType;
import cn.b.sky.mes.mm.service.InventoryService;
import cn.b.sky.mes.mm.service.MoveTypeService;
import cn.b.sky.common.exception.ImeException;
import cn.b.sky.common.model.ImeCommon;
import cn.b.sky.i18n.utils.LocaleResourceBundle;
import cn.b.sky.user.SecurityContextUtil;
import cn.b.sky.user.service.ParameterService;
import cn.b.sky.user.service.model.ParameterEntity;
import cn.b.sky.mes.pp.dao.OperationConfirmDao;
import cn.b.sky.mes.pp.dao.OperationTaskDao;
import cn.b.sky.mes.pp.dao.ProductOrderDao;
import cn.b.sky.mes.pp.dao.ProductionControlDao;
import cn.b.sky.mes.pp.dao.ProductionOrderConfirmDao;
import cn.b.sky.mes.pp.dao.ProductionOrderDao;
import cn.b.sky.mes.pp.enums.OperationTaskComfirmType;
import cn.b.sky.mes.pp.enums.OperationTaskStatus;
import cn.b.sky.mes.pp.enums.OrderStatusCode;
import cn.b.sky.mes.pp.enums.PorderStatusCode;
import cn.b.sky.mes.pp.enums.ProductionControlStatusCode;
import cn.b.sky.mes.pp.model.OperationTask;
import cn.b.sky.mes.pp.model.OperationTaskConfirm;
import cn.b.sky.mes.pp.model.ProductOrder;
import cn.b.sky.mes.pp.model.ProductionControl;
import cn.b.sky.mes.pp.model.ProductionOrder;
import cn.b.sky.mes.pp.service.RequirementStrategyService;

/**
 * 
 * <strong>Title : OperationConfirmServiceImpl.java<br></strong>
 * <strong>Package : cn.b.sky.mes.pp.service.impl<br></strong>
 * <strong>Description : </strong>工序确认实现类<br>
 * <strong>Create on : 2016年8月8日 下午1:25:42<br></strong>
 * <p>
 * @author zhaoxin01<br>
 * @version <strong>v1.0.0</strong><br>
 * <br>
 * <strong>修改历史:</strong><br>
 * 修改人|修改日期|修改描述<br>
 * -------------------------------------------<br>
 * <br>
 * <br>
 */
@Service("operationConfirmService")
public class OperationConfirmServiceImpl implements OperationConfirmService {

  // 日志对象
  protected static final Logger LOGGER = LoggerFactory.getLogger(OperationConfirmServiceImpl.class);

  @Resource
  ProductionOrderConfirmDao productionOrderConfirmDao;

  @Resource
  OperationConfirmDao operationConfirmDao;

  @Resource
  WorkUnitService workUnitService;

  @Resource
  OperationTaskDao operationTaskDao;

  @Resource
  ProductionControlDao productionControlDao;

  @Resource
  ProductionOrderDao productionOrderDao;

  @Resource
  ProductOrderDao productOrderDao;

  @Resource
  private EvunProcessEngine skyProcessEngine;

  @Resource
  MoveTypeService moveTypeService;

  @Resource
  ProcessService processService;

  @Resource
  InventoryService inventoryService;

  @Resource
  RequirementStrategyService requirementStrategyService;

  @Resource
  ParameterService parameterService;

  private static final String PULL_STRATEGY_ENABLE = "PULL_STRATEGY_ENABLE";

  private static final String CONFIRMBYLASTOPERA = "CONFIRMBYLASTOPERA";

  @Override
  public OperationTask selectOperationTask(String siteCode, String operationTaskNum, String languageCode,
                                           String eCodeType) {
    return operationConfirmDao.selectOperationTask(siteCode, operationTaskNum, languageCode, eCodeType);
  }

  @Override
  public boolean doValidaUnitType(String siteCode, String workUnitCode, String workUnitTypeCode) {
    int n = operationConfirmDao.doValidaUnitType(siteCode, workUnitCode, workUnitTypeCode);
    return n > 0;
  }

  @Override
  public boolean doValidaPersonnel(String siteCode, String personnelCode, String workCenterCode) {
    int n = operationConfirmDao.doValidaPersonnel(siteCode, personnelCode, workCenterCode);
    return n > 0;
  }

  @Override
  public void doConfirmOperationTask(OperationTaskConfirm operationTaskConfirm) {
    //检查任务单状态是否已经变化
    OperationTask operationTask = operationConfirmDao.selectOperationTaskForConfirm(operationTaskConfirm.getSiteCode(),
        operationTaskConfirm.getOperationTaskNum());
    if (!operationTaskConfirm.getTaskStatus().equals(operationTask.getStatusECode())) {
      throw ImeException.newException("operationTaskHasChanged.M");
    }
    //检查任务单可报工数量
    double canConfirmQty = operationTask.getPlannedQuantity().doubleValue()
        - operationTask.getCompletedQuantity().doubleValue();
    if (operationTaskConfirm.getCompletedQuantity().doubleValue() > canConfirmQty) {
      //throw ImeException.newException("confirmQtyOver.M", new String[] { canConfirmQty + "" });
      String message = LocaleResourceBundle.getCommonResourceLabel(operationTaskConfirm.getSiteCode(),
          SecurityContextUtil.getLanguageCode(), "confirmQtyOver.M",
          new String[] {NumberUtils.subZeroAndDot(Double.toString(canConfirmQty)) });
      throw new RuntimeException(message);
    }
    Date date = new Date();
    operationTaskConfirm.setConfirmDateTime(date);
    operationTaskConfirm.setProductionControlNum(operationTask.getProductionControlNum());
    operationTaskConfirm.setProductionOrderNum(operationTask.getProductionOrderNum());
    operationTaskConfirm.setWorkCenterCode(operationTask.getWorkCenterCode());
    //执行报工
    //    insertOperationTaskConfirm(operationTaskConfirm);
    //    updateOperationTask(operationTaskConfirm);
    //    updateProductionControl(operationTaskConfirm);
    //    updateProductionOrder(operationTaskConfirm);
    //    updateProductOrder(operationTaskConfirm);
    Map<String, Object> map = new HashMap<String, Object>();
    String tenantId = operationTaskConfirm.getSiteCode();
    // 变量生产订单
    map.put("operationTaskConfirm", operationTaskConfirm);
    map.put("tenantId", tenantId);
    skyProcessEngine.startProcessByKeyAndTenantId(map, "operationConfirm_process", tenantId);
  }

  private void setChangeInfo(ImeCommon imeCommon) {
    imeCommon.setModifyDateTime(new Date());
    imeCommon.setModifyUser(SecurityContextUtil.getCurrentUserName());
  }

  private void setCreateInfo(ImeCommon imeCommon) {
    imeCommon.setCreateDateTime(new Date());
    imeCommon.setCreateUser(SecurityContextUtil.getCurrentUserName());
    imeCommon.setModifyDateTime(new Date());
    imeCommon.setModifyUser(SecurityContextUtil.getCurrentUserName());
  }

  @Override
  public void insertOperationTaskConfirm(OperationTaskConfirm operationTaskConfirm) {
    //补全信息
    if (OperationTaskComfirmType.CONFIRM.getValue().equals(operationTaskConfirm.getConfirmTypeeCode())) {
      //查询最近的一条开始或恢复类型的记录
      OperationTaskConfirm otc = operationConfirmDao.getLastTypeOperationTaskConfirm(operationTaskConfirm.getSiteCode(),
          operationTaskConfirm.getOperationTaskNum(), OperationTaskComfirmType.START.getValue());
      OperationTaskConfirm otc1 = operationConfirmDao.getLastTypeOperationTaskConfirm(
          operationTaskConfirm.getSiteCode(), operationTaskConfirm.getOperationTaskNum(),
          OperationTaskComfirmType.RECOVER.getValue());
      Date start = otc.getConfirmDateTime();
      if (otc1 != null) {
        start = otc.getConfirmDateTime().after(otc1.getConfirmDateTime()) ? otc.getConfirmDateTime()
            : otc1.getConfirmDateTime();
      }
      //设置开始时间
      operationTaskConfirm.setStartDateTime(start);
    }
    if (OperationTaskComfirmType.RECOVER.getValue().equals(operationTaskConfirm.getConfirmTypeeCode())) {
      //查询最近的一条暂停类型的记录
      OperationTaskConfirm otc = operationConfirmDao.getLastTypeOperationTaskConfirm(operationTaskConfirm.getSiteCode(),
          operationTaskConfirm.getOperationTaskNum(), OperationTaskComfirmType.PAUSE.getValue());
      //设置开始时间
      operationTaskConfirm.setStartDateTime(otc.getConfirmDateTime());
    }
    setCreateInfo(operationTaskConfirm);
    operationConfirmDao.insertOperationTaskConfirm(operationTaskConfirm);
  }

  @Override
  public void updateOperationTask(OperationTaskConfirm operationTaskConfirm) {
    OperationTask operationTask = operationConfirmDao.selectOperationTaskForConfirm(operationTaskConfirm.getSiteCode(),
        operationTaskConfirm.getOperationTaskNum());
    operationTask.setLastPersonnelCode(operationTaskConfirm.getPersonnelCode());
    operationTask.setLastWorkUnitCode(operationTaskConfirm.getWorkUnitCode());
    if (OperationTaskComfirmType.START.getValue().equals(operationTaskConfirm.getConfirmTypeeCode())) {
      //开始
      operationTask.setStatusECode(OperationTaskStatus.INTO_PRODUCTION.getValue());
      //记录实际开始时间
      if (operationTask.getActualStartDateTime() == null) {
        operationTask.setActualStartDateTime(operationTaskConfirm.getConfirmDateTime());
      }
    } else if (OperationTaskComfirmType.CONFIRM.getValue().equals(operationTaskConfirm.getConfirmTypeeCode())) {
      //报工
      Double total = operationTask.getCompletedQuantity() + operationTaskConfirm.getCompletedQuantity();
      operationTask.setCompletedQuantity(total);
      operationTask
          .setScrappedQuantity(operationTask.getScrappedQuantity() + operationTaskConfirm.getScrappedQuantity());
      if (total.doubleValue() == operationTask.getPlannedQuantity().doubleValue()) {
        //设置完工状态
        operationTask.setStatusECode(OperationTaskStatus.COMPLETE.getValue());
        //设置实际结束时间
        operationTask.setActualEndDateTime(operationTaskConfirm.getConfirmDateTime());
      } else {
        //设置报工状态
        operationTask.setStatusECode(OperationTaskStatus.SUBMIT.getValue());
      }
      //计算工时
      Double hours = calHours(operationTaskConfirm);
      Double beforeHours = operationTask.getActualHours() != null ? operationTask.getActualHours() : 0;
      operationTask.setActualHours(beforeHours + hours);
    } else if (OperationTaskComfirmType.PAUSE.getValue().equals(operationTaskConfirm.getConfirmTypeeCode())) {
      //暂停
      operationTask.setStatusECode(OperationTaskStatus.PAUSE.getValue());
      //计算工时
      Double hours = calHours(operationTaskConfirm);
      Double beforeHours = operationTask.getActualHours() != null ? operationTask.getActualHours() : 0;
      operationTask.setActualHours(beforeHours + hours);
    } else if (OperationTaskComfirmType.RECOVER.getValue().equals(operationTaskConfirm.getConfirmTypeeCode())) {
      //恢复
      operationTask.setStatusECode(OperationTaskStatus.INTO_PRODUCTION.getValue());
    }
    setChangeInfo(operationTask);
    operationTaskDao.updateOperationTaskForConfirm(operationTask);
  }

  /**
   * 
   * <strong>Title : calHours<br></strong>
   * <strong>Description : </strong>计算工时<br> 
   * <strong>Create on : 2016年8月10日 上午10:52:52<br></strong>
   * <p>
   * @param operationTaskConfirm
   * @return
   * Double
   * @throws 
   * @author zhaoxin01<br>
   * @version <strong>v1.0.0</strong><br>
   * <br>
   * <strong>修改历史:</strong><br>
   * 修改人 | 修改日期 | 修改描述<br>
   * -------------------------------------------<br>
   * <br>
   * <br>
   */
  private Double calHours(OperationTaskConfirm operationTaskConfirm) {
    //查询最近的一条开始或恢复类型的记录
    OperationTaskConfirm otc = operationConfirmDao.getLastTypeOperationTaskConfirm(operationTaskConfirm.getSiteCode(),
        operationTaskConfirm.getOperationTaskNum(), OperationTaskComfirmType.START.getValue());
    OperationTaskConfirm otc1 = operationConfirmDao.getLastTypeOperationTaskConfirm(operationTaskConfirm.getSiteCode(),
        operationTaskConfirm.getOperationTaskNum(), OperationTaskComfirmType.RECOVER.getValue());
    Date start = otc.getConfirmDateTime();
    if (otc1 != null) {
      start = otc.getConfirmDateTime().after(otc1.getConfirmDateTime()) ? otc.getConfirmDateTime()
          : otc1.getConfirmDateTime();
    }
    long seconds = operationTaskConfirm.getConfirmDateTime().getTime() - start.getTime();
    Double hours = seconds / 3600000.0d;
    return hours;
  }

  @Override
  public void updateProductionControl(OperationTaskConfirm operationTaskConfirm) {
    //查询最少的一个工序完成数量和报废数量汇总
    ProductionControl info = operationConfirmDao.selectOperationTaskCompletedQuantity(
        operationTaskConfirm.getSiteCode(), operationTaskConfirm.getProductionControlNum());
    info.setSiteCode(operationTaskConfirm.getSiteCode());
    info.setProductionControlNum(operationTaskConfirm.getProductionControlNum());

    boolean confirmBylast = false;
    try {
      ParameterEntity entity = parameterService.getParameterEntityByCode(CONFIRMBYLASTOPERA,
          operationTaskConfirm.getSiteCode());
      confirmBylast = !StringUtils.isEmpty(entity.getDefaultValue())
          && Integer.valueOf(entity.getDefaultValue()).intValue() == 1;
    } catch (Exception e) {
      LOGGER.error("{}", e);
    }
    if (confirmBylast) {
      //只按最后一道确认点工序的完成数量做为生产管理号的完成数量
      int completedQty = operationConfirmDao.selectLastOperationCompletedQuantity(operationTaskConfirm.getSiteCode(),
          operationTaskConfirm.getProductionControlNum());
      info.setCompletedQuantity(Double.parseDouble(Integer.toString(completedQty)));
    }
    //查询生产管理号
    ProductionControl dinfo = productionControlDao.selectProductionControl(operationTaskConfirm.getSiteCode(),
        operationTaskConfirm.getProductionControlNum());
    if (dinfo.getActualstartDateTime() == null) {
      info.setActualstartDateTime(operationTaskConfirm.getConfirmDateTime());
    }
    if (dinfo.getPlannedQuantity().doubleValue() == info.getCompletedQuantity().doubleValue()) {
      info.setStatuseCode(ProductionControlStatusCode.COMPLETE.getValue());
      if (!dinfo.getStatuseCode().equals(ProductionControlStatusCode.COMPLETE.getValue())) {
        info.setActualendDateTime(operationTaskConfirm.getConfirmDateTime());
      }
    } else {
      info.setStatuseCode(ProductionControlStatusCode.SUBMIT.getValue());
    }
    setChangeInfo(info);
    productionControlDao.updateProductionControl(info);
  }

  @Override
  public void updateProductionOrder(OperationTaskConfirm operationTaskConfirm) {
    //汇总生产管理号最少的一笔完成数量和报废数量
    ProductionOrder info = productionOrderDao.selectOrderCompletedQuantity(operationTaskConfirm.getSiteCode(),
        operationTaskConfirm.getProductionOrderNum());
    info.setSiteCode(operationTaskConfirm.getSiteCode());
    info.setProductionOrderNum(operationTaskConfirm.getProductionOrderNum());
    //查询生产订单
    ProductionOrder dinfo = productionOrderDao.selectProductionOrdersByPk(operationTaskConfirm.getSiteCode(),
        operationTaskConfirm.getProductionOrderNum());
    info.setMaterialCode(dinfo.getMaterialCode());
    info.setProductMaterialCode(dinfo.getProductMaterialCode());
    info.setProductOrderNum(dinfo.getProductOrderNum());
    if (dinfo.getActualstartDateTime() == null) {
      info.setActualstartDateTime(operationTaskConfirm.getConfirmDateTime());
    }
    if (dinfo.getPlannedQuantity().doubleValue() == info.getCompletedQuantity().doubleValue()) {
      info.setStatuseCode(OrderStatusCode.COMPLETE.getValue());
      if (!dinfo.getStatuseCode().equals(OrderStatusCode.COMPLETE.getValue())) {
        info.setActualendDateTime(operationTaskConfirm.getConfirmDateTime());
      }
    } else {
      List<String> controlStatusSet = new ArrayList<String>();
      controlStatusSet.add(ProductionControlStatusCode.CREATE.getValue());
      controlStatusSet.add(ProductionControlStatusCode.ISSUED.getValue());
      controlStatusSet.add(ProductionControlStatusCode.PRODUCT.getValue());
      controlStatusSet.add(ProductionControlStatusCode.SUBMIT.getValue());
      int count = productionControlDao.selectProductionControlCountByStatusSet(info.getSiteCode(),
          info.getProductionOrderNum(), controlStatusSet);
      if (count == 0) {
        info.setStatuseCode(OrderStatusCode.CLOSE.getValue());
        info.setActualendDateTime(new Date());
      } else {
        info.setStatuseCode(OrderStatusCode.PLACE_ORDER.getValue());
      }
    }
    setChangeInfo(info);
    productionOrderDao.updateProductionOrder(info);
  }

  @Override
  public void updateProductOrder(OperationTaskConfirm operationTaskConfirm) {
    //查询生产订单
    ProductionOrder info = productionOrderDao.selectProductionOrdersByPk(operationTaskConfirm.getSiteCode(),
        operationTaskConfirm.getProductionOrderNum());
    if (!StringUtils.isBlank(info.getProductOrderNum())) {
      if (info.getMaterialCode().equals(info.getProductMaterialCode())) {
        //如果生产订单的物料和产品订单一致，则更新产品订单数量和状态
        ProductOrder pOrder = new ProductOrder();
        pOrder.setSiteCode(info.getSiteCode());
        pOrder.setProductOrderNum(info.getProductOrderNum());
        pOrder.setCompletedQuantity(info.getCompletedQuantity());
        pOrder.setScrappedQuantity(info.getScrappedQuantity());
        ProductOrder productOrder = productOrderDao.selectProductOrdersByPk(info.getSiteCode(),
            info.getProductOrderNum());
        if (productOrder.getActualstartDateTime() == null) {
          pOrder.setActualstartDateTime(operationTaskConfirm.getConfirmDateTime());
        }
        if (info.getStatuseCode().equals(OrderStatusCode.COMPLETE.getValue())
            || info.getStatuseCode().equals(OrderStatusCode.CLOSE.getValue())) {
          if (isProductOrderCompleteOrClose(pOrder.getSiteCode(), pOrder.getProductOrderNum())) {
            if (isHasClosedProductionOrder(pOrder.getSiteCode(), pOrder.getProductOrderNum())) {
              pOrder.setStatuseCode(PorderStatusCode.CLOSE.getValue());
            } else {
              pOrder.setStatuseCode(PorderStatusCode.COMPLETE.getValue());
            }
            pOrder.setActualendDateTime(info.getActualendDateTime());
          }
        }
        pOrder.setModifyUser(info.getModifyUser());
        pOrder.setModifyDateTime(operationTaskConfirm.getConfirmDateTime());
        productOrderDao.updateNoCreateProductOrder(pOrder);
      } else if (isProductOrderCompleteOrClose(info.getSiteCode(), info.getProductOrderNum())) {
        //如果生产订单的物料和产品订单一致，则更新产品订单状态
        ProductOrder pOrder = new ProductOrder();
        pOrder.setSiteCode(info.getSiteCode());
        pOrder.setProductOrderNum(info.getProductOrderNum());
        if (isHasClosedProductionOrder(pOrder.getSiteCode(), pOrder.getProductOrderNum())) {
          pOrder.setStatuseCode(PorderStatusCode.CLOSE.getValue());
        } else {
          pOrder.setStatuseCode(PorderStatusCode.COMPLETE.getValue());
        }
        pOrder.setActualendDateTime(info.getActualendDateTime());
        pOrder.setModifyUser(info.getModifyUser());
        pOrder.setModifyDateTime(operationTaskConfirm.getConfirmDateTime());
        productOrderDao.updateNoCreateProductOrder(pOrder);
      }
    }
  }

  @Override
  public void doOperationBuckleMaterial(OperationTaskConfirm operationTaskConfirm) {
    MoveType moveType = moveTypeService.getMoveType(operationTaskConfirm.getSiteCode(), MmConstant.MOVETYPECODE);
    if (moveType == null || StringUtils.isBlank(moveType.getMoveTypeCode())) {
      throw ImeException.newException("notExstisBackflush.C", MmConstant.MOVETYPECODE.split(","));
    }
    OperationTask task = operationTaskDao.getoperationTask(operationTaskConfirm.getSiteCode(),
        operationTaskConfirm.getOperationTaskNum());
    if (task == null || StringUtils.isBlank(task.getOperationTaskNum())) {
      return;
    }
    ProcessOperation processOperation = processService.getProcessOperationById(task.getProcessOperationId());
    if (processOperation != null) {
      List<ProcessComponent> components = processService
          .getProcessComponentByProcessOperation(processOperation.getId());
      if (components != null && components.size() > 0) {
        double quantity = operationTaskConfirm.getCompletedQuantity() + operationTaskConfirm.getScrappedQuantity();
        for (ProcessComponent component : components) {
          inventoryService.productBuckleMaterial(operationTaskConfirm.getSiteCode(),
              operationTaskConfirm.getWorkUnitCode(), operationTaskConfirm.getWorkCenterCode(),
              quantity * component.getQuantity().doubleValue(), component.getComponentCode());
        }
      }
      //生产基于安全库存策略的物料需求
      boolean isPull = false;
      try {
        ParameterEntity entity = parameterService.getParameterEntityByCode(PULL_STRATEGY_ENABLE,
            processOperation.getSiteCode());
        isPull = !StringUtils.isEmpty(entity.getDefaultValue())
            && Integer.valueOf(entity.getDefaultValue()).intValue() == 1;
      } catch (Exception e) {
        String message = LocaleResourceBundle.getCommonResourceLabel(processOperation.getSiteCode(),
            SecurityContextUtil.getLanguageCode(), "pullStrategyEnable.M");
        throw new RuntimeException(message);
      }
      if (isPull) {
        requirementStrategyService.createSafetyInventoryRequirements(operationTaskConfirm);
      }
    }
  }

  /**
   * 
   * <strong>Title : isProductOrderCompleteOrClose<br></strong>
   * <strong>Description : </strong>产品订单是否应该完工或关闭<br> 
   * <strong>Create on : 2016年5月19日 下午1:09:50<br></strong>
   * <p>
   * @param siteCode
   * @param ProductOrderNum
   * @return
   * boolean
   * @throws 
   * @author zhaoxin01<br>
   * @version <strong>v1.0.0</strong><br>
   * <br>
   * <strong>修改历史:</strong><br>
   * 修改人 | 修改日期 | 修改描述<br>
   * -------------------------------------------<br>
   * <br>
   * <br>
   */
  private boolean isProductOrderCompleteOrClose(String siteCode, String ProductOrderNum) {
    List<String> orderStatusSet = new ArrayList<String>();
    orderStatusSet.add(OrderStatusCode.CREATE.getValue());
    orderStatusSet.add(OrderStatusCode.PLACE_ORDER.getValue());
    return productionOrderDao.selectOrderCountByStatusSet(siteCode, ProductOrderNum, orderStatusSet) == 0;
  }

  private boolean isHasClosedProductionOrder(String siteCode, String ProductOrderNum) {
    List<String> closeStatusSet = new ArrayList<String>();
    closeStatusSet.add(OrderStatusCode.CLOSE.getValue());
    return productionOrderDao.selectOrderCountByStatusSet(siteCode, ProductOrderNum, closeStatusSet) > 0;
  }

}
